package org.catpay.modules.sys.oauth2;

import java.io.IOException;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.catpay.common.utils.HttpContextUtils;
import org.catpay.common.utils.JsonUtil;
import org.catpay.common.utils.RedisUtils;
import org.catpay.modules.sys.entity.SysUserEntity;
import org.catpay.modules.sys.entity.SysUserTokenEntity;
import org.catpay.modules.sys.utils.R;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.RequestMethod;

import cn.hutool.core.util.StrUtil;

/**
 * oauth2过滤器
 *
 */
@Component
public class OAuth2Filter extends AccessControlFilter {

	private String[] URL = {"/webjars", "/druid",
			 "/app", "/sys/login", 
			 "/swagger", "/v2/api-docs", "/swagger-ui.html",
			 "/swagger-resources", "/captcha.jpg" ,
			 "/static","/login.html"
						   };

	@Autowired
	private RedisUtils redisUtils;

	@Override
	protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue)
			throws Exception {
		HttpServletRequest req = (HttpServletRequest) request;
		for (String url : URL) {
			if (req.getRequestURI().indexOf(url) > -1) {
				return true;
			}
		}

		if (req.getMethod().equals(RequestMethod.OPTIONS.name())) {
			return true;
		}
		String token = getRequestToken(req);
		if (StringUtils.isBlank(token)) {
			hanldeLoseToken((HttpServletResponse) response,"invalid token");
			return false;
		}
		Object obj =  SecurityUtils.getSubject().getPrincipal();
		if(obj == null) {
			hanldeLoseToken((HttpServletResponse) response,"session超时，请重新登录");
			return false;
		}
		SysUserEntity user = (SysUserEntity) obj;
		String result = redisUtils.get(String.valueOf(user.getUserId()));
		if (StringUtils.isNotBlank(result)) {
			SysUserTokenEntity sysUserTokenEntity = JsonUtil.getInstance().json2obj(result, SysUserTokenEntity.class);
			if(sysUserTokenEntity == null) {
				hanldeLoseToken((HttpServletResponse) response,"token失效，请重新登录");
				return false;
			}
			
			if(!token.equals(sysUserTokenEntity.getToken())) {
				hanldeLoseToken((HttpServletResponse) response,"token错误");
				return false;
			}
			
		}else {
			hanldeLoseToken((HttpServletResponse) response,"token失效，请重新登录");
			return false;
		}

		return true;
	}

	private void hanldeLoseToken(HttpServletResponse httpResponse, String msg) throws Exception {
		httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
		httpResponse.setHeader("Access-Control-Allow-Origin", HttpContextUtils.getOrigin());
		httpResponse.setContentType("application/json; charset=utf-8");
		String json = JsonUtil.getInstance().obj2json(R.error(HttpStatus.SC_MOVED_TEMPORARILY, msg));
		IOUtils.write(json, httpResponse.getOutputStream(), "utf-8");
	}
	
	@Override
	protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException {
		String xReq = ((HttpServletRequest) request).getHeader("X-Requested-With");
		if (StrUtil.isBlank(xReq) || !"XMLHttpRequest".equalsIgnoreCase(xReq)) {
			redirectToLogin(request, response);
		}
		return false;
	}

	/**
	 * 获取请求的token
	 */
	private String getRequestToken(HttpServletRequest httpRequest) {
		// 从header中获取token
		String token = httpRequest.getHeader("token");

		// 如果header中不存在token，则从参数中获取token
		if (StringUtils.isBlank(token)) {
			token = httpRequest.getParameter("token");
		}

		return token;
	}

}
